package com.design_patterns.singleton;

import java.io.Serializable;

/**
 * @author: 李德才
 * @description:
 * @create: 2020-08-23 15:53
 **/

/**
 * 双重校验
 */
public class DoubleCheck implements Serializable {

    /**
     * ------> volatile:
     * 在 JIT 情况中
     * 防止JAVA虚拟机的指令重排返回没有初始化好的对象,需要添加 volatile
     */
    private static volatile DoubleCheck INSTANCE;

    private DoubleCheck() {

    }

    /**
     * 在需要加锁的时候加锁
     * 不满足只有一个实例
     *
     * @return
     */
    public static DoubleCheck getInstance() {
//        当 INSTANCE == null 时继续执行，否则直接返回
        if (INSTANCE == null) {
//            上锁
            synchronized (DoubleCheck.class) {
//                第二次检查INSTANCE是否有值，如果有值则直接返回，否则继续执行
//                因为加上了synchronized 锁，这时其他线程无法进入，这里就是双重检查
                if (INSTANCE == null) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new DoubleCheck();
                }
            }
        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.err.println(DoubleCheck.getInstance().hashCode());
            }).start();
        }
    }
}
